package com.xinbochuang.machine.admin.service.impl.system;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinbochuang.machine.admin.domain.StorageRack;
import com.xinbochuang.machine.admin.domain.system.*;
import com.xinbochuang.machine.admin.mapper.system.SysStorehouseInMapper;
import com.xinbochuang.machine.admin.mapper.system.SysStorehouseMapper;
import com.xinbochuang.machine.admin.service.IStorageRackService;
import com.xinbochuang.machine.admin.service.system.*;
import com.xinbochuang.machine.common.annotation.DataScope;
import com.xinbochuang.machine.common.domain.LoginUser;
import com.xinbochuang.machine.common.enums.StoreHouseStatus;
import com.xinbochuang.machine.common.enums.UserStatus;
import com.xinbochuang.machine.common.exception.CustomException;
import com.xinbochuang.machine.common.utils.QrCodeUtil;
import com.xinbochuang.machine.common.utils.SecurityUtils;
import com.xinbochuang.machine.common.utils.ServletUtils;
import com.xinbochuang.machine.framework.web.service.TokenService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 黄晓鹏
 * @date 2020-09-27
 */
@Service
public class SysStorehouseInServiceImpl extends ServiceImpl<SysStorehouseInMapper, SysStorehouseIn> implements ISysStorehouseInService {

    @Resource
    private SysStorehouseInMapper storehouseInMapper;

    @Resource
    private ISysStorehouseInBackupService storehouseInBackupService;

    @Resource
    private ISysStorehouseSecondService storehouseSecondService;

    @Resource
    private ISysStorehouseService storehouseService;

    @Resource
    private SysStorehouseMapper storehouseMapper;

    @Resource
    private ISysStorehouseSecondBackupService sysStorehouseSecondBackupService;

    @Resource
    private TokenService tokenService;

    @Resource
    private IStorageRackService storageRackService;

    private final ReentrantLock lock = new ReentrantLock();

    /**
     * 查询入库分页列表
     *
     * @param storehouseIn 入库
     * @return 结果
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysStorehouseIn> selectList(SysStorehouseIn storehouseIn) {
        if (storehouseIn.getPageNum() != null && storehouseIn.getPageSize() != null) {
            storehouseIn.setBegin((storehouseIn.getPageNum() - 1) * 10);
            storehouseIn.setEnd(storehouseIn.getPageNum() * storehouseIn.getPageSize());
        } else {
            throw new CustomException("分页参数错误！");
        }

        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (storehouseIn.getType().equals("0")) {
            SysUser user = loginUser.getUser();
            List<SysRole> roles = user.getRoles();
            for (SysRole sysRole : roles) {
                if (sysRole.getRoleKey().equals("manager")) {
                    storehouseIn.setStatus("0");
                }
                if (sysRole.getRoleKey().equals("managerAdmin")) {
                    storehouseIn.setStatus("2");
                }
            }
            storehouseIn.setUserId(loginUser.getUser().getUserId());
        }

        return storehouseInMapper.selectStorehouseInList(storehouseIn);
    }

    /**
     * 根据主键查询入库表
     *
     * @param inId 主键
     * @return 结果
     */
    @Override
    public SysStorehouseIn selectById(Integer inId) {
        SysStorehouseIn storehouseIn = getById(inId);
        // 查询一级清单
        SysStorehouse storehouse = storehouseService.getOne(new QueryWrapper<SysStorehouse>().lambda().eq(SysStorehouse::getInId, inId).last("and rownum = 1"));
        // 查询二级清单
        storehouseIn.setChildren(selectChildren(storehouse));
        return storehouseIn;
    }

    /**
     * 根据一级清单id查询二级清单列表
     *
     * @param storehouse 一级清单
     * @return 二级清单
     */
    private List<SysStorehouseSecond> selectChildren(SysStorehouse storehouse) {
        return storehouseSecondService.list(new QueryWrapper<SysStorehouseSecond>().lambda().eq(SysStorehouseSecond::getFirstId, storehouse.getId()));
    }

    /**
     * 插入入库表
     *
     * @param storehouseInList 入库集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertStorehouseIn(List<SysStorehouseIn> storehouseInList) {
        lock.lock();
        try {
            // 批量插入入库表
            for (SysStorehouseIn storehouseIn : storehouseInList) {
                storehouseIn.setCreateBy(SecurityUtils.getUsername());
                storehouseIn.setCreateTime(DateUtil.now());
            }
            saveBatch(storehouseInList);
            // 插入备份表
            List<SysStorehouseInBackup> storehouseInBackupList = new ArrayList<>();
            for (SysStorehouseIn sysStorehouseIn : storehouseInList) {
                SysStorehouseInBackup storehouseInBackup = new SysStorehouseInBackup(sysStorehouseIn);
                storehouseInBackupList.add(storehouseInBackup);
            }
            storehouseInBackupService.saveBatch(storehouseInBackupList);
            String now = DateUtil.now();
            String createBy = SecurityUtils.getUsername();
            // 当天最后一个code
            String lastCode = storehouseMapper.selectLastCodeToday();
            // 当前排序数字
            int num = QrCodeUtil.currentNum(lastCode);
            // 有几条申请，就插入几条一级清单
            for (SysStorehouseIn storehouseIn : storehouseInList) {
                List<SysStorehouse> storehouseList = new ArrayList<>();
                for (int i = 0; i < storehouseIn.getNum(); i++) {
                    SysStorehouse storehouse = new SysStorehouse(storehouseIn);
                    // 根据规则生成二维码字符串：WG-20200930-001
                    String code = QrCodeUtil.code(num);
                    storehouse.setCode(code);
                    storehouse.setCreateBy(createBy);
                    storehouse.setCreateTime(now);
                    storehouseList.add(storehouse);
                    num++;
                }
                // 批量插入一级清单
                storehouseService.saveBatch(storehouseList);
                for (SysStorehouse storehouse : storehouseList) {
                    // 插入二级清单
                    if (storehouse.getChildren() != null && !storehouse.getChildren().isEmpty()) {
                        insertSeconds(storehouse);
                    }
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 修改入库表
     *
     * @param storehouseIn 入库
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStorehouseIn(SysStorehouseIn storehouseIn) {
        lock.lock();
        try {
            String now = DateUtil.now();
            String updateBy = SecurityUtils.getUsername();
            storehouseIn.setUpdateBy(updateBy);
            storehouseIn.setUpdateTime(now);
            // 修改入库表
            updateById(storehouseIn);
            // 修改备份表
            SysStorehouseInBackup storehouseInBackup = new SysStorehouseInBackup(storehouseIn);
            storehouseInBackupService.updateById(storehouseInBackup);
            // 循环删除一级清单/二级清单
            List<SysStorehouse> storehouseList = storehouseService.list(new QueryWrapper<SysStorehouse>().lambda().eq(SysStorehouse::getInId, storehouseIn.getInId()));
            List<Integer> ids = new ArrayList<>();
            for (SysStorehouse storehouse : storehouseList) {
                storehouseSecondService.remove(new QueryWrapper<SysStorehouseSecond>().lambda().eq(SysStorehouseSecond::getFirstId, storehouse.getId()));
                ids.add(storehouse.getId());
            }
            // 当天最后一个code
            String lastCode = storehouseMapper.selectLastCodeToday();
            // 当前排序数字
            int num = QrCodeUtil.currentNum(lastCode);
            storehouseService.removeByIds(ids);
            // 重新插入一级/二级
            List<SysStorehouse> storehouseAddList = new ArrayList<>();
            for (int i = 0; i < storehouseIn.getNum(); i++) {
                SysStorehouse storehouse = new SysStorehouse(storehouseIn);
                // 根据规则生成二维码字符串：WG-20200930-001

                String code = QrCodeUtil.code(num);
                storehouse.setCode(code);
                storehouse.setCreateBy(storehouseIn.getCreateBy());
                storehouse.setCreateTime(storehouseIn.getCreateTime());
                storehouse.setUpdateBy(updateBy);
                storehouse.setUpdateTime(now);
                storehouseAddList.add(storehouse);
                num++;
            }
            // 批量插入一级清单
            storehouseService.saveBatch(storehouseAddList);
            for (SysStorehouse storehouse : storehouseAddList) {
                // 插入二级清单
                if (storehouse.getChildren() != null && !storehouse.getChildren().isEmpty()) {
                    insertSeconds(storehouse);
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 插入二级清单
     *
     * @param storehouse 一级清单
     */
    private void insertSeconds(SysStorehouse storehouse) {
        List<SysStorehouseSecond> secondList = storehouse.getChildren();
        List<SysStorehouseSecondBackup> secondBackupList = new ArrayList<>();
        for (SysStorehouseSecond sysStorehouseSecond : secondList) {
            sysStorehouseSecond.setFirstId(storehouse.getId());
            sysStorehouseSecond.setCreateBy(storehouse.getCreateBy());
            sysStorehouseSecond.setCreateTime(storehouse.getCreateTime());
            SysStorehouseSecondBackup sysStorehouseSecondBackup = new SysStorehouseSecondBackup(sysStorehouseSecond);
            secondBackupList.add(sysStorehouseSecondBackup);
        }
        storehouseSecondService.saveBatch(secondList);
        sysStorehouseSecondBackupService.saveBatch(secondBackupList);
    }

    /**
     * 批量删除入库表
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    public boolean deleteByIds(Integer[] ids) {
        List<SysStorehouseIn> storehouseInList = new ArrayList<>();
        for (Integer id : ids) {
            SysStorehouseIn storehouseIn = new SysStorehouseIn();
            storehouseIn.setInId(id);
            storehouseIn.setDelFlag(UserStatus.DELETED.getCode());
            storehouseInList.add(storehouseIn);
        }
        return updateBatchById(storehouseInList);
    }

    /**
     * 查询未删除的/在库的物品信息
     *
     * @return 在库列表
     */
    @Override
    public List<SysStorehouse> online() {
        //查询申请表
        QueryWrapper<SysStorehouseIn> queryWrapper = new QueryWrapper<>();
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysUser user = loginUser.getUser();
        queryWrapper.lambda().eq(SysStorehouseIn::getDelFlag, 0).eq(SysStorehouseIn::getStatus, StoreHouseStatus.IN.getCode()).eq(SysStorehouseIn::getDeptId, user.getDeptId());
        List<SysStorehouseIn> list = list(queryWrapper);
        //根据申请表查询一级/二级
        List<SysStorehouse> storehouseList = new ArrayList<>();
//        for (SysStorehouseIn sysStorehouseIn : list) {
        //查询一级清单
        List<SysStorehouse> storehouses = storehouseService.list(Wrappers.<SysStorehouse>lambdaQuery().eq(SysStorehouse::getDeptId, user.getDeptId()).eq(SysStorehouse::getStatus, StoreHouseStatus.IN.getCode()));
        for (SysStorehouse storehouse : storehouses) {
            // 查询二级清单
            List<SysStorehouseSecond> children = storehouseSecondService.list(new QueryWrapper<SysStorehouseSecond>().lambda().eq(SysStorehouseSecond::getFirstId, storehouse.getId()));
            storehouse.setChildren(children);
        }
        storehouseList.addAll(storehouses);
//        }
        return storehouseList;
    }

    /**
     * 修改入库状态
     *
     * @param storehouseIn 入库
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(SysStorehouseIn storehouseIn) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysStorehouseIn sysStorehouseIn = storehouseInMapper.selectById(storehouseIn.getInId());
        // 修改入库状态
        String name = SecurityUtils.getUsername();
        String now = DateUtil.now();
        storehouseIn.setUpdateBy(name);
        storehouseIn.setUpdateTime(now);
        if (storehouseIn.getStatus().equals(StoreHouseStatus.READYPASS.getCode())) {
            storehouseIn.setApproveBy(loginUser.getUsername());
            storehouseIn.setApproveTime(now);
        } else if (storehouseIn.getStatus().equals(StoreHouseStatus.NOMAIL.getCode())) {
            storehouseIn.setConfirmBy(loginUser.getUsername());
            storehouseIn.setConfirmTime(now);
        }
        updateById(storehouseIn);
        // 修改一级清单状态
        List<SysStorehouse> storehouseList = storehouseService.list(Wrappers.<SysStorehouse>lambdaQuery().eq(SysStorehouse::getInId, storehouseIn.getInId()));
        for (SysStorehouse storehouse : storehouseList) {
            storehouse.setUpdateBy(name);
            storehouse.setUpdateTime(now);
            storehouse.setStatus(storehouseIn.getStatus());
        }
        storehouseService.updateBatchById(storehouseList);
        return true;
    }

    @Override
    public List<SysStorehouse> storelist(SysStorehouseIn storehouseIn) {
        if (storehouseIn.getPageNum() != null && storehouseIn.getPageSize() != null) {
            storehouseIn.setBegin((storehouseIn.getPageNum() - 1) * 10);
            storehouseIn.setEnd(storehouseIn.getPageNum() * storehouseIn.getPageSize());
        } else {
            throw new CustomException("分页参数错误！");
        }
        List<SysStorehouse> list = storehouseInMapper.selectStorehouseList(storehouseIn);
        for (SysStorehouse sysStorehouse : list) {
            SysStorehouseSecond second = storehouseSecondService.getOne(Wrappers.<SysStorehouseSecond>lambdaQuery().eq(SysStorehouseSecond::getFirstId, sysStorehouse.getId()).last("and rownum <= 1"));
            if (second != null && second.getNum() != null) {
                sysStorehouse.setNum(second.getNum().toString());
            } else {
                sysStorehouse.setNum("1");
            }

            StringBuilder sb = new StringBuilder();
            if (sysStorehouse.getStorageRackId() != null) {
                StorageRack storageRack = storageRackService.getOne(Wrappers.<StorageRack>lambdaQuery().eq(StorageRack::getId, sysStorehouse.getStorageRackId()).last("and rownum <= 1"));
                if (storageRack != null) {
                    sb.append(storageRack.getCode());
                }
            }
            if (sysStorehouse.getStorageRackPosition() != null) {
                sb.append(sysStorehouse.getStorageRackPosition());
            }
            sysStorehouse.setStorageRackName(sb.toString());
        }
        return list;
    }

    /**
     * 查询导出待办列表
     *
     * @param storehouseIn 查询条件
     * @return 结果
     */
    @Override
    public List<SysStorehouseIn> selectExportList(SysStorehouseIn storehouseIn) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (storehouseIn.getType().equals("0")) {
            SysUser user = loginUser.getUser();
            List<SysRole> roles = user.getRoles();
            for (SysRole sysRole : roles) {
                if (sysRole.getRoleKey().equals("manager")) {
                    storehouseIn.setStatus("0");
                }
                if (sysRole.getRoleKey().equals("managerAdmin")) {
                    storehouseIn.setStatus("2");
                }
            }
            storehouseIn.setUserId(loginUser.getUser().getUserId());
        }
        return storehouseInMapper.selectExportList(storehouseIn);
    }

    /**
     * 查询导出库存列表
     *
     * @param storehouseIn 查询条件
     * @return 结果
     */
    @Override
    public List<SysStorehouse> selectExportStoreList(SysStorehouseIn storehouseIn) {
        List<SysStorehouse> list = storehouseInMapper.selectExportStoreList(storehouseIn);
        for (SysStorehouse sysStorehouse : list) {
            SysStorehouseSecond second = storehouseSecondService.getOne(Wrappers.<SysStorehouseSecond>lambdaQuery().eq(SysStorehouseSecond::getFirstId, sysStorehouse.getId()).last("and rownum <= 1"));
            if (second != null && second.getNum() != null) {
                sysStorehouse.setNum(second.getNum().toString());
            } else {
                sysStorehouse.setNum("1");
            }

            StringBuilder sb = new StringBuilder();
            if (sysStorehouse.getStorageRackId() != null) {
                StorageRack storageRack = storageRackService.getOne(Wrappers.<StorageRack>lambdaQuery().eq(StorageRack::getId, sysStorehouse.getStorageRackId()).last("and rownum <= 1"));
                if (storageRack != null) {
                    sb.append(storageRack.getCode());
                }
            }
            if (sysStorehouse.getStorageRackPosition() != null) {
                sb.append(sysStorehouse.getStorageRackPosition());
            }
            sysStorehouse.setStorageRackName(sb.toString());

            if (sysStorehouse.getIsExist().equals("Y")) {
                sysStorehouse.setIsExist("是");
            } else {
                sysStorehouse.setIsExist("否");
            }
        }
        return list;
    }
}
